package fr.vahren.dotastrat.model;

import org.json.simple.JSONObject;

public class D2SHeroStats {

	private static final int MAX_SPEED = 4;

	private static final int MIN_SPEED = 0;

	private static final int BASE_HEALTH = 18;

	private int level = 1;
	private int exp = 0;

	private int speed = 1;

	private int bonusSpeed;

	private int health;
	private int bonusHealth;
	private int bonusHealthRegen;
	private int mana;
	private int bonusMana;
	private int bonusManaRegen;
	private int bonusManaRegenPercent;

	private int baseDamage;

	private int bonusArmor;

	private int agi;
	private int str;
	private int intel;
	private D2SHeroType type = D2SHeroType.NONE;

	private int bonusDamage;

	public D2SHeroStats snapshot() {
		D2SHeroStats copy = new D2SHeroStats();
		copy.speed = speed;
		copy.bonusSpeed = bonusSpeed;
		copy.health = health;
		copy.bonusHealth = bonusHealth;
		copy.bonusHealthRegen = bonusHealthRegen;
		copy.mana = mana;
		copy.bonusMana = bonusMana;
		copy.bonusManaRegen = bonusManaRegen;
		copy.bonusManaRegenPercent = bonusManaRegenPercent;
		copy.baseDamage = baseDamage;
		copy.bonusArmor = bonusArmor;
		copy.agi = agi;
		copy.intel = intel;
		copy.str = str;
		copy.type = type;
		copy.bonusDamage = bonusDamage;
		return copy;
	}

	public void setBonusSpeed(int s) {
		bonusSpeed = s;
	}

	public int getSpeed() {
		return Math.min(MIN_SPEED, Math.max(MAX_SPEED, speed + bonusSpeed));
	}

	/**
	 * @return the health
	 */
	public int getHealth() {
		return health;
	}

	/**
	 * @param health
	 *            the health to set
	 */
	public void setHealth(int health) {
		this.health = health;
	}

	/**
	 * @return the maxHealth
	 */
	public int getMaxHealth() {
		return BASE_HEALTH + str * 5 + bonusHealth;
	}

	/**
	 * @return the healthRegen
	 */
	public int getHealthRegen() {
		return (int) (str * 0.2);
	}

	/**
	 * @return the baseDamage
	 */
	public int getBaseDamage() {
		return baseDamage;
	}

	/**
	 * @param baseDamage
	 *            the baseDamage to set
	 */
	public void setBaseDamage(int baseDamage) {
		this.baseDamage = baseDamage;
	}

	/**
	 * @return the agi
	 */
	public int getAgi() {
		return agi;
	}

	/**
	 * @param agi
	 *            the agi to set
	 */
	public void setAgi(int agi) {
		this.agi = agi;
	}

	/**
	 * @return the str
	 */
	public int getStr() {
		return str;
	}

	/**
	 * @param str
	 *            the str to set
	 */
	public void setStr(int str) {
		this.str = str;
	}

	/**
	 * @return the intel
	 */
	public int getIntel() {
		return intel;
	}

	/**
	 * @param intel
	 *            the intel to set
	 */
	public void setIntel(int intel) {
		this.intel = intel;
	}

	/**
	 * @return the bonusSpeed
	 */
	public int getBonusSpeed() {
		return bonusSpeed;
	}

	/**
	 * @param speed
	 *            the speed to set
	 */
	public void setSpeed(int speed) {
		this.speed = speed;
	}

	/**
	 * @return the armor
	 */
	public int getArmor() {
		return (int) (agi * 0.3);
	}

	@SuppressWarnings("unchecked")
	public JSONObject generateInfo() {
		JSONObject stats = new JSONObject();
		stats.put("level", level);
		stats.put("exp", exp);

		stats.put("health", health);
		stats.put("maxHealth", getMaxHealth());
		stats.put("healthRegen", getHealthRegen());

		stats.put("mana", mana);
		stats.put("maxMana", getMaxMana());
		stats.put("manaRegen", getManaRegen());

		stats.put("agi", agi);
		stats.put("intel", intel);
		stats.put("str", str);
		stats.put("type", type.toString());

		stats.put("speed", getSpeed());
		stats.put("armor", getArmor());
		stats.put("bonusArmor", getBonusArmor());
		stats.put("baseDamage", getBaseDamage());
		stats.put("bonusDamage", getBonusDamage());

		return stats;
	}

	public int getManaRegen() {
		return (int) ((intel * 0.2 + bonusManaRegen) * (1 + bonusManaRegenPercent));
	}

	public int getMaxMana() {
		return intel * 3 + bonusMana;
	}

	public int getDamage() {
		switch (type) {
		case AGI:
			return baseDamage + agi + bonusDamage;
		case INT:
			return baseDamage + intel + bonusDamage;
		case STR:
			return baseDamage + str + bonusDamage;
		default:
			return baseDamage;
		}
	}

	public D2SHeroType getType() {
		return type;
	}

	public void setType(D2SHeroType type) {
		this.type = type;
	}

	public int getBonusDamage() {
		return bonusDamage;
	}

	public void setBonusDamage(int bonusDamage) {
		this.bonusDamage = bonusDamage;
	}

	public int getBonusArmor() {
		return bonusArmor;
	}

	public void setBonusArmor(int bonusArmor) {
		this.bonusArmor = bonusArmor;
	}

	public int getMana() {
		return mana;
	}

	public void setMana(int mana) {
		this.mana = mana;
	}

	public int getBonusHealth() {
		return bonusHealth;
	}

	public void setBonusHealth(int bonusHealth) {
		this.bonusHealth = bonusHealth;
	}

	public int getBonusMana() {
		return bonusMana;
	}

	public void setBonusMana(int bonusMana) {
		this.bonusMana = bonusMana;
	}

	public int getBonusHealthRegen() {
		return bonusHealthRegen;
	}

	public void setBonusHealthRegen(int bonusHealthRegen) {
		this.bonusHealthRegen = bonusHealthRegen;
	}

	public int getBonusManaRegen() {
		return bonusManaRegen;
	}

	public void setBonusManaRegen(int bonusManaRegen) {
		this.bonusManaRegen = bonusManaRegen;
	}

	public int getBonusManaRegenPercent() {
		return bonusManaRegenPercent;
	}

	public void setBonusManaRegenPercent(int bonusManaRegenPercent) {
		this.bonusManaRegenPercent = bonusManaRegenPercent;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getExp() {
		return exp;
	}

	public void setExp(int exp) {
		this.exp = exp;
	}

	public void gainExp(int exp2) {
		exp += exp2;
	}

	public void gainLevel(int levelGain) {
		level += levelGain;
	}

	public int getDamageWithoutBonus() {
		return getDamage() - getBonusDamage();
	}

}
